package com.moshang.blog.shiro.realm;

import com.google.common.collect.Sets;
import com.moshang.blog.config.shiro.ShiroUtil;
import com.moshang.blog.core.constant.Constants;
import com.moshang.blog.core.constant.CurrentUser;
import com.moshang.blog.entity.SysMenu;
import com.moshang.blog.entity.SysRole;
import com.moshang.blog.entity.SysUser;
import com.moshang.blog.service.SiteService;
import com.moshang.blog.core.utils.Encodes;
import com.moshang.blog.service.SysUsersService;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Set;

/**
 * @program: blog
 * @description: ${description}
 * @author: xieweiwei
 * @create: 2018-09-20 13:58
 **/
public class MyShiroRealm extends AuthorizingRealm {
    @Resource
    @Lazy
    private SysUsersService sysUsersService;
    @Autowired
    @Lazy
    private SiteService siteService;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

        CurrentUser currentUser = (CurrentUser)principals.getPrimaryPrincipal();
        SysUser user = sysUsersService.findUserByLoginName(currentUser.getUserName());
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        Set<SysRole> roles = user.getRoleLists();
        Set<String> roleNames = Sets.newHashSet();
        for (SysRole role : roles) {
            if(StringUtils.isNotBlank(role.getRoleName())){
                roleNames.add(role.getRoleName());
            }
        }
        Set<SysMenu> menus = user.getMenus();
        Set<String> permissions = Sets.newHashSet();
        for (SysMenu menu : menus) {
            if(StringUtils.isNotBlank(menu.getPermission())){
                permissions.add(menu.getPermission());
            }
        }
        info.setRoles(roleNames);
        info.setStringPermissions(permissions);

        return info;
    }

    /*主要是用来进行身份认证的，也就是说验证用户输入的账号和密码是否正确。*/
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken)
            throws AuthenticationException {

        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        Subject subject = ShiroUtil.getSubjct();
        String username = (String) token.getPrincipal();
        SysUser user = sysUsersService.findByUserName(username);
        Session session= subject.getSession();
        if (user == null) {
            throw new UnknownAccountException();//没找到帐号
        }
        if (user.getLocked()==1) {
            throw new LockedAccountException(); //帐号锁定
        }
        CurrentUser currentUser=new CurrentUser( user.getId(), user.getUserName(),user.getRealName(),user.getPassword(),user.getAge(),user.getEmail(), user.getImage());

        byte[] salt = Encodes.decodeHex(user.getSalt());
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                new CurrentUser( user.getId(), user.getUserName(),user.getRealName(),user.getPassword(),user.getAge(),user.getEmail(), user.getImage()),
                user.getPassword(), //密码
                ByteSource.Util.bytes(salt),
                getName()  //realm name
        );
        session.setAttribute("currentUser",currentUser);
        session.setAttribute("site",siteService.getCurrentSite());
        return authenticationInfo;
    }
    /**
     * 设定Password校验的Hash算法与迭代次数.
     */
    @PostConstruct
    public void initCredentialsMatcher() {
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher(Constants.HASH_ALGORITHM);
        matcher.setHashIterations(Constants.HASH_INTERATIONS);
        setCredentialsMatcher(matcher);
    }
    /**
     * 清理缓存权限
     */
    public void clearCachedAuthorizationInfo()
    {
        this.clearCachedAuthorizationInfo(SecurityUtils.getSubject().getPrincipals());
    }

}
